/**
 * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springblade.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.common.constant.ProtocolConstant;
import org.springblade.common.tool.NetUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.ObjectUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.entity.InstalledAnalysis;
import org.springblade.entity.Product;
import org.springblade.entity.ProtocolAnalysis;
import org.springblade.feign.IDeviceConnectClient;
import org.springblade.service.IInstalledAnalysisService;
import org.springblade.service.IProtocolAnalysisService;
import org.springblade.vo.ProductVO;
import org.springblade.mapper.ProductMapper;
import org.springblade.service.IProductService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;

import java.util.ArrayList;
import java.util.List;

/**
 * 服务实现类
 * @author Blade
 * @since 2023-04-12
 */
@Service
public class ProductServiceImpl extends BaseServiceImpl<ProductMapper, Product> implements IProductService {

	@Lazy
	@Autowired
	private IInstalledAnalysisService installedAnalysisService;

	@Lazy
	@Autowired
	private IProtocolAnalysisService protocolAnalysisService;

	@Autowired
	@Lazy
	private IDeviceConnectClient deviceConnectClient;

	@Override
	public IPage<ProductVO> selectProductPage(IPage<ProductVO> page, ProductVO product) {
		return page.setRecords(baseMapper.selectProductPage(page, product));
	}

	/**
	 * up or down socket
	 * @param product
	 */
	@Override
	public void upOrDownSocket(Product product) {
		Product oldProduct = this.getOne(Wrappers.<Product>lambdaQuery().eq(Product::getIpAddr, product.getIpAddr()).eq(Product::getPort, product.getPort()));
		if (oldProduct == null) {
			oldProduct = product;
		}
		BeanUtils.copyProperties(product, oldProduct);
		this.saveOrUpdate(oldProduct, Wrappers.<Product>lambdaUpdate().eq(Product::getIpAddr, product.getIpAddr()).eq(Product::getPort, product.getPort()));
	}

	/**
	 * 重新连接
	 * @param ids
	 * @return
	 */
	@Override
	public R<Boolean> reconnection(String ids) {
		try {
			String[] idL = ids.split(",");
			List<Product> products = this.list(Wrappers.<Product>lambdaQuery().eq(Product::getIsDeleted, 0).in(Product::getId, idL).in(Product::getProtocol, ProtocolConstant.TCP_SERVER, ProtocolConstant.TCP_CLIENT));
			for (Product product : products) {
				deviceConnectClient.reconnection(product.getIpAddr(), product.getPort(), product.getProtocol());
			}
			return R.status(true);
		} catch (Exception e) {
			e.printStackTrace();
			return R.status(false);
		}
	}

	/**
	 * 新增或修改
	 * @param product
	 * @return
	 */
	@Override
	public R saveOrUpdateFromAnalysis(Product product) {
		try {
			// check ip/port/protocol
			Product oldProduct = this.getOne(Wrappers.<Product>lambdaQuery().eq(Product::getIsDeleted, 0).eq(Product::getIpAddr, product.getIpAddr()).eq(Product::getProtocol, product.getProtocol()).eq(Product::getPort, product.getPort()));
			if (ObjectUtil.isNotEmpty(oldProduct)) {
				product.setId(oldProduct.getId());
				this.updateById(product);
			} else {
				product.setOnline(1);
				this.saveOrUpdate(product);
				// 内置规则查找
				List<InstalledAnalysis> analysisList = installedAnalysisService.list(Wrappers.<InstalledAnalysis>lambdaQuery().eq(InstalledAnalysis::getProductTypeId, product.getType()));
				List<ProtocolAnalysis> protocolS = new ArrayList<>();
				for (InstalledAnalysis analysis : analysisList) {
					ProtocolAnalysis protocolAnalysis = new ProtocolAnalysis();
					BeanUtils.copyProperties(analysis, protocolAnalysis);
					protocolAnalysis.setId(null);
					protocolAnalysis.setProductId(product.getId());
					protocolS.add(protocolAnalysis);
				}
				protocolAnalysisService.saveBatch(protocolS);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return R.status(false);
		}
		return R.status(true);
	}

	/**
	 * 删除产品并将附带协议表删除
	 * @param ids
	 * @return
	 */
	@Override
	public R removeAndProtocol(String ids) {
		try {
			List<Long> idList = Func.toLongList(ids);
			this.deleteLogic(idList);
			protocolAnalysisService.remove(Wrappers.<ProtocolAnalysis>lambdaQuery().in(ProtocolAnalysis::getProductId, idList));
		} catch (Exception e) {
			e.printStackTrace();
			return R.status(false);
		}
		return R.status(true);
	}

	/**
	 * 连通性测试
	 * @param ids
	 * @return
	 */
	@Override
	public R<Boolean> testIpAndPort(String ids) {
		if (StringUtil.isBlank(ids)) {
			List<Product> products = this.list(Wrappers.<Product>lambdaQuery().eq(Product::getIsDeleted, 0));
			for (Product product : products) {
				Boolean aBoolean = NetUtil.testIpAndPort(product.getIpAddr(), product.getPort(), 3000);
				int online = aBoolean ? 0 : 1;
				product.setOnline(online);
				this.updateById(product);
			}
			return R.status(true);
		} else {
			String[] idL = ids.split(",");
			Product product = this.getOne(Wrappers.<Product>lambdaQuery().eq(Product::getId, idL[0]).eq(Product::getIsDeleted, 0));
			Boolean aBoolean = NetUtil.testIpAndPort(product.getIpAddr(), product.getPort(), 3000);
			int online = aBoolean ? 0 : 1;
			product.setOnline(online);
			this.updateById(product);
			return R.status(aBoolean);
		}
	}

}
